package com.hitqz.robot.dispatch.netty.strategy.zhiqingDispather;


import cn.hutool.extra.spring.SpringUtil;
import com.google.common.cache.Cache;
import com.hitqz.robot.api.business.dto.RobotClientSummaryDto;
import com.hitqz.robot.api.business.dto.RobotLaserPosDto;
import com.hitqz.robot.api.dispatch.protocol.dto.RobotCmdNavDto;
import com.hitqz.robot.api.dispatch.protocol.dto.RobotDto;
import com.hitqz.robot.dispatch.netty.util.DispatchUtil;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import org.locationtech.jts.geom.Polygon;

import java.util.Set;

/**
 * 申请线程，基于区域互斥
 */
@Slf4j
public class ApplyThread implements Runnable {
    public static volatile Boolean running = true;
    RobotDto robotDto;
    BlockedContext blockedContext;
    boolean isInBlockAreaLast = false;
    private volatile boolean applicationInit = false;
    private  long startTime = System.currentTimeMillis();
    /**
     * 如果不是因为程序初始化，而是因为导航无法获取到为止，就不要休眠了
     */
    private volatile boolean needSleep = true;

    public ApplyThread(RobotDto robotDto, BlockedContext blockedContext) {
        this.robotDto = robotDto;
        this.blockedContext = blockedContext;
    }

    @Override
    public void run() {
        log.info("{}-{}避障线程开启", robotDto.getRobotSn(), robotDto.getRobotName());
        while (running) {
            Polygon agvPolygon = getPolygon();
            if (agvPolygon == null) {
                if (!applicationInit) {
                    try {

                        // blockedContext
                        Thread.sleep(1000);
                        log.info("程序刚刚启动，无位置信息，休息1s");
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                } else {
                    needSleep = false;
                }
                continue;
            }

            try {
                applicationInit = true;
                if (needSleep) {
                    Thread.sleep(200);
                }
                boolean isInBlockArea = ZhiqingStrategyUtil.isPositionInBoundingBox(agvPolygon,
                        blockedContext.bufferedPolygon);

                if (isInBlockArea == isInBlockAreaLast) {
                    if (System.currentTimeMillis() - startTime > 1000) {
/*
                        log.info("{}-{}：{}阻塞区域", robotDto.getRobotSn(), robotDto.getRobotName(), isInBlockArea ? "在" :
                                "不在");
*/
                        startTime = System.currentTimeMillis();
                    }
                   /* if (isInBlockArea) {
                        log.info("{} 的 position:{}", this, agvPolygon);
                    }*/
                    continue;
                }
                //进入阻塞区域
                else if (isInBlockArea && !isInBlockAreaLast) {
                    synchronized (BlockedContext.lock) {
                        Boolean applySuccess = BlockedContext.apply(robotDto);
                        //已经有车站着阻塞位置，停止导航，直到另外一辆离开
                        if (!applySuccess) {
                            try {
                                //todo 判断导航状态
                                //发送停止命令，并等待释放锁，
                                log.info("暂停导航");
                                try {
                                    changeNavStatus(robotDto.getRobotSn(), 1);
                                } catch (Exception e) {
                                    log.info("{}:{}停止导航失败", robotDto.getRobotSn(), robotDto.getRobotName());
                                }
                                //
                                //如果多辆车的话需要重新申请才能开始导航
                                BlockedContext.lock.wait();


                                while (true) {
                                    log.info("申请阻塞区域");
                                    applySuccess = BlockedContext.apply(robotDto);
                                    if (applySuccess) {
                                        log.info("恢复导航");
                                        //继续到指定为止
                                        changeNavStatus(robotDto.getRobotSn(), 2);
                                        break;
                                    } else {
                                        BlockedContext.lock.wait();
                                    }
                                }


                            } catch (InterruptedException e) {
                                Thread.currentThread().interrupt(); // 恢复中断状态
                                log.error("等待被中断", e);
                            }
                        }
                    }

                }


                //离开阻塞区域
                else {

                    log.info("离开阻塞区域");

                    synchronized (BlockedContext.lock) {
                        BlockedContext.release(robotDto);
                    }


                }
                isInBlockAreaLast = isInBlockArea;

            } catch (Exception e) {
                log.error("调度异常，导航取消{},", e.getStackTrace(), e);
            }


        }


    }

    @Nullable
    private Polygon getPolygon() {
        Cache<String, Polygon> robotCache = SpringUtil.getBean("robotPosPolygon");

        Polygon polygon = robotCache.getIfPresent(robotDto.getRobotSn());

        return polygon;
    }

    public synchronized void interupt() {
        if (running) {
            running = false;
        }
    }

    private Position getPosition() {
        RobotClientSummaryDto robotStatus = DispatchUtil.getRobotStatus(robotDto.getRobotSn());
        RobotLaserPosDto laserPos = robotStatus.getPosition().getLaserPos();
        return new Position(laserPos.getX(), laserPos.getY());
    }

    /**
     * 修改导航状态
     *
     * @param clientId
     * @param status
     */
    public static void changeNavStatus(String clientId, int status) {
        SpringUtil.getApplicationContext().publishEvent(new RobotCmdNavDto(clientId, status));
    }

}
